#include "Divider_Randomize.h"

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <fstream>
#include <sstream>

using namespace std;

Divider_Randomize::Divider_Randomize(void)
{
}

Divider_Randomize::~Divider_Randomize(void)
{
}

VOID Divider_Randomize::initialize(IN STRING _arg)
{
    m_Size = 200;
    if (_arg.size() != 0)
    {
        m_Size = atoi(_arg.c_str());
    }
}

SparseDataSet* Divider_Randomize::constructData(IN DividerInfo::InfoPair& _info)
{
    SparseDataSet* ret = m_MemManager->newT(ret);
    ret->setBufferSize(m_Options->getDataBufferSize());
    ret->regMemoryManager(m_MemManager);
    ret->initialize();
    ret->LoadData(_info.dividedModel);
    return ret;
}

DividerInfo Divider_Randomize::divide(
                                      IN DOUBLE _dataLabel, 
                                      IN LabelInfo* _labelInfo, 
                                      IN STRING _dir, 
                                      IN STRING _dataName, 
                                      IN INT _proRank)
{

    srand(UINT32(time(NULL)));
    LabelInfo::InfoPair* curInfo = &(_labelInfo->info.find(_dataLabel)->second);

    m_rndNum = INT(curInfo->count * log(1.0 * curInfo->count));
/*
    SparseDataSet* sds = m_MemManager->newT(sds);
    sds->setBufferSize(m_Options->getDataBufferSize());
    sds->regMemoryManager(m_MemManager);
    sds->initialize();
    sds->LoadData(curInfo->fileLocation);
*/

/*
    for (INT tms = 0; tms < m_rndNum; ++tms)
    {
        INT v1, v2;
        v1 = rand() % sds->dataSet.size();
        v2 = rand() % sds->dataSet.size();
        while (v1 == v2)
        {
            v2 = rand() % sds->dataSet.size();
        }
        Util::swap(sds->dataSet[v1], sds->dataSet[v2]);
    }
*/

    UINT32 partNum = curInfo->count / m_Size;
    UINT32 retNum = curInfo->count % m_Size;
    partNum += (retNum != 0);
    retNum = curInfo->count % partNum;
    UINT32 realSize = curInfo->count / partNum;
    UINT32 barRank = retNum % partNum;

    CHAR* m_Buf = m_MemManager->newT_A(m_Buf, m_Options->getDataBufferSize());//**
    FILE* fin = fopen(curInfo->fileLocation.c_str(), "r");//**

    DividerInfo ret;
    INT cid = 0;
    for (INT rnk = 0; rnk < partNum; ++rnk)
    {
        stringstream namess;
        namess << _dir << "/" << "__proc" << _proRank << "."
            << _dataName << ".L["
            << _dataLabel << "].P["
            << rnk << "]";
        ofstream fout(namess.str().c_str());
        for (INT i = realSize + (rnk < barRank) - 1; i >= 0; --i, ++cid)
        {
/*
            fout << sds->dataSet[cid]->toString() << endl;
*/
            fgets(m_Buf, m_Options->getDataBufferSize(), fin); //**
            fout << m_Buf;//**
        }
        fout.close();
        for (INT i = 0; i < _labelInfo->labelSet.size(); ++i)
        {
            if (_labelInfo->labelSet[i] == _dataLabel)
            {
                continue;
            }
            DividerInfo::InfoPair ip;
            ip.label = _dataLabel;
            ip.vsLabel = _labelInfo->labelSet[i];
            ip.partId = rnk;
            ip.size = realSize + (rnk < barRank);
            ip.dividedModel = namess.str();
            ret.infoSet.push_back(ip);
        }
    }
/*
    m_MemManager->deleteT(sds);
*/
    m_MemManager->deleteT(m_Buf);
    fclose(fin);

    return ret;
}

